package fr.jhaccoun.demenager_eco.utilisateur;

import java.math.BigDecimal;
import java.util.TreeSet;

import javax.sql.DataSource;

import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.FileSystemResource;
import org.springframework.core.io.Resource;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.transaction.TransactionConfiguration;
import org.springframework.test.jdbc.JdbcTestUtils;
import org.springframework.transaction.annotation.Transactional;

import com.github.springtestdbunit.MyDbUnitRule;
import com.github.springtestdbunit.annotation.DatabaseSetup;

import fr.jhaccoun.demenager_eco.produit.Categorie;
import fr.jhaccoun.demenager_eco.produit.EtatUsure;
import fr.jhaccoun.demenager_eco.produit.Produit;
import fr.jhaccoun.demenager_eco.produit.Taille;
 
@ContextConfiguration(locations = { "classpath:applicationContextTest.xml" })
@RunWith(SpringJUnit4ClassRunner.class)
@TransactionConfiguration(transactionManager = "transactionManager", defaultRollback = false)
@Transactional
 public class ITUtilisateurServiceImpl {
	 
	@Autowired
	private UtilisateurService utilisateurService;
   
	@Rule
	public MyDbUnitRule dbUnit = new MyDbUnitRule();
	
	@Autowired
	private DataSource dataSource;
	   
 	@After
	public void cleanData(){ 
		Resource scriptResetData = new FileSystemResource("src/main/resources/sql/reset_data.sql");
		JdbcTemplate jdbc = new JdbcTemplate(dataSource);  
		JdbcTestUtils.executeSqlScript(jdbc, scriptResetData, false); 
	}
	
	@Test
	@DatabaseSetup({"classpath:data/insert_produit_categorie.xml","classpath:data/insert_produit_etat_usure.xml"}) 
	public void testAddUtilisateur_NouvelUtilisateur() throws UserAlreadyExistsException {
 
		EtatUsure etatUsure = new EtatUsure();
		etatUsure.setId(0L);
		
		Categorie cat = new Categorie();
		cat.setId(0L);
		
		Produit p1ToAdd = new Produit();
		p1ToAdd.setReference("HUD-VFFF-31312");
		p1ToAdd.setDescription("congelateur derniere game avec retro eclairage puis ecran lumineux");
		p1ToAdd.setIntitule("congelateur UHV 157894 PC");
		p1ToAdd.setGaranti(true);
		p1ToAdd.setFacture(false);
		p1ToAdd.setMarque("BRANDT");
		p1ToAdd.setPoids(76);
		p1ToAdd.setPrixVente(new BigDecimal(125.54));
		p1ToAdd.setTaille(new Taille(50,60,120));
		p1ToAdd.setCategorie(cat);
		p1ToAdd.setEtatUsure(etatUsure);
		
		Utilisateur user = new Utilisateur(); 
		user.setNom("merlin");
		user.setPrenom("arthur");
		user.setEmail("nouveluser@gmail.com");
		user.setPassword("mdp");
		
		user.addProduit(p1ToAdd);
		
		utilisateurService.addUtilisateur(user); 
		
		Utilisateur utilisateurRetreived = utilisateurService.findByEmail("nouveluser@gmail.com");
 
		assertUtilisateurFields(utilisateurRetreived,user);
		
		Assert.assertEquals(1,utilisateurRetreived.getProduits().size());
		Produit p1Retreived = utilisateurRetreived.getProduits().get(0);
		 
		assertProduitFields(p1Retreived,p1ToAdd,user); 
	}
	
	
	@Test(expected = UserAlreadyExistsException.class) 
	@DatabaseSetup({"classpath:data/insert_utilisateurs.xml"}) 
	public void testAddUtilisateur_Failed_UtilisateurExistant() throws UserAlreadyExistsException { 
		Utilisateur user = new Utilisateur(); 
		user.setNom("merlin");
		user.setPrenom("arthur");
		user.setEmail("user1@gmail.com");
		user.setPassword("mdp");
		 
		utilisateurService.addUtilisateur(user); 		 
	}
	
	//TODO TEst Unitaire : Rendre plus générique la vérification , ptet une lib existe pr checker par reflection chaque champs
	
	private void assertUtilisateurFields(Utilisateur utilisateurActual,Utilisateur UtilisateurExpected){
		Assert.assertNotNull(utilisateurActual);
		Assert.assertNotNull(UtilisateurExpected);
		Assert.assertEquals(UtilisateurExpected.getEmail(),utilisateurActual.getEmail());
		Assert.assertEquals(UtilisateurExpected.getNom(),utilisateurActual.getNom());
		Assert.assertEquals(UtilisateurExpected.getPrenom(),utilisateurActual.getPrenom());
		Assert.assertEquals(UtilisateurExpected.getUsername(),utilisateurActual.getUsername());
		Assert.assertEquals(UtilisateurExpected.getActif(),utilisateurActual.getActif());
		Assert.assertEquals(UtilisateurExpected.getAuthorities(),utilisateurActual.getAuthorities());
		Assert.assertEquals(UtilisateurExpected.getRoles(),utilisateurActual.getRoles());
		Assert.assertEquals(UtilisateurExpected.getPassword(),utilisateurActual.getPassword()); 
	}
	
	private void assertProduitFields(Produit produitActual,Produit produitExpected,Utilisateur UtilisateurExpected){
		Assert.assertNotNull(produitActual);
		Assert.assertNotNull(produitExpected);

		Assert.assertEquals(produitExpected.getDescription(),produitActual.getDescription());
		Assert.assertEquals(produitExpected.getIntitule(),produitActual.getIntitule());
		Assert.assertEquals(produitExpected.getMarque(),produitActual.getMarque());
		Assert.assertEquals(produitExpected.getReference(),produitActual.getReference());
		Assert.assertEquals(produitExpected.getCategorie(),produitActual.getCategorie());
		Assert.assertEquals(produitExpected.getEtatUsure(),produitActual.getEtatUsure());
		Assert.assertEquals(produitExpected.getFacture(),produitActual.getFacture());
		Assert.assertEquals(produitExpected.getGaranti(),produitActual.getGaranti());
		Assert.assertEquals(produitExpected.getPoids(),produitActual.getPoids());
		Assert.assertEquals(produitExpected.getPrixVente(),produitActual.getPrixVente());
		Assert.assertEquals(produitExpected.getTaille(),produitActual.getTaille());
		
		Utilisateur utilisateurDuProduit = produitActual.getUtilisateur(); 
		Assert.assertEquals(UtilisateurExpected,utilisateurDuProduit);
	}
	
 
	
 
}
